import fs from "fs/promises";
import path from "path";

/**
 * Configuration reader for include/exclude directory settings
 */
export class ConfigReader {
  private configDir: string;

  constructor(workingDirectory: string) {
    this.configDir = path.join(workingDirectory, '.codebase-rag');
  }

  /**
   * Read include directories from .codebase-rag/.include-dirs
   * Returns empty array if file doesn't exist
   */
  async readIncludeDirs(): Promise<string[]> {
    try {
      const includeFile = path.join(this.configDir, '.include-dirs');
      const content = await fs.readFile(includeFile, 'utf-8');
      return this.parseConfigFile(content);
    } catch (error) {
      // File doesn't exist or can't be read, return empty array
      return [];
    }
  }

  /**
   * Read exclude directories from .codebase-rag/.exclude-dirs  
   * Returns empty array if file doesn't exist
   */
  async readExcludeDirs(): Promise<string[]> {
    try {
      const excludeFile = path.join(this.configDir, '.exclude-dirs');
      const content = await fs.readFile(excludeFile, 'utf-8');
      return this.parseConfigFile(content);
    } catch (error) {
      // File doesn't exist or can't be read, return empty array
      return [];
    }
  }

  /**
   * Parse configuration file content into array of directory patterns
   * - One pattern per line
   * - Lines starting with # are comments
   * - Empty lines are ignored
   * - Whitespace is trimmed
   * - Directory names are automatically made recursive (e.g., "docs" becomes "docs/**")
   */
  private parseConfigFile(content: string): string[] {
    return content
      .split('\n')
      .map(line => line.trim())
      .filter(line => line.length > 0 && !line.startsWith('#'))
      .map(pattern => this.normalizePattern(pattern));
  }

  /**
   * Normalize a pattern to ensure directory patterns are recursive
   * - "docs" becomes "docs/**"
   * - "docs/" becomes "docs/**" 
   * - "docs/**" stays "docs/**"
   * - "*.md" stays "*.md"
   * - "src/*.js" stays "src/*.js"
   */
  private normalizePattern(pattern: string): string {
    // If pattern already contains glob characters (*, ?, [, ]), leave it as is
    if (pattern.includes('*') || pattern.includes('?') || pattern.includes('[')) {
      return pattern;
    }

    // If pattern looks like a directory name (no file extension or ends with /)
    // make it recursive by adding /**
    const trimmedPattern = pattern.endsWith('/') ? pattern.slice(0, -1) : pattern;
    
    // Check if it looks like a directory (no file extension)
    const hasFileExtension = /\.[a-zA-Z0-9]+$/.test(trimmedPattern);
    
    if (!hasFileExtension) {
      return `${trimmedPattern}/**`;
    }
    
    // Keep file patterns as is
    return pattern;
  }

  /**
   * Check if configuration directory exists
   */
  async configExists(): Promise<boolean> {
    try {
      const stats = await fs.stat(this.configDir);
      return stats.isDirectory();
    } catch (error) {
      return false;
    }
  }

  /**
   * Create configuration directory if it doesn't exist
   */
  async ensureConfigDir(): Promise<void> {
    try {
      await fs.mkdir(this.configDir, { recursive: true });
    } catch (error) {
      // Directory might already exist, ignore error
    }
  }

  /**
   * Create example configuration files
   */
  async createExampleConfigs(): Promise<void> {
    await this.ensureConfigDir();

    const includeExample = `# Include directories - one per line
# Use glob patterns like those used in .gitignore
# Examples:
src/
docs/
*.md
# **/*.ts`;

    const excludeExample = `# Exclude directories - one per line  
# Use glob patterns like those used in .gitignore
# Examples:
node_modules/
.git/
dist/
build/
coverage/
*.log
# **/*.test.js`;

    try {
      const includeFile = path.join(this.configDir, '.include-dirs');
      const excludeFile = path.join(this.configDir, '.exclude-dirs');

      // Only create if files don't exist
      try {
        await fs.access(includeFile);
      } catch {
        await fs.writeFile(includeFile, includeExample);
      }

      try {
        await fs.access(excludeFile);
      } catch {
        await fs.writeFile(excludeFile, excludeExample);
      }
    } catch (error) {
      console.warn('Failed to create example configuration files:', error);
    }
  }
}